x86/mca: MCA bank clear
authorLiu, Jinsong <jinsong.liu@intel.com>
Thu, 12 May 2011 07:53:42 +0000 (08:53 +0100)
committerLiu, Jinsong <jinsong.liu@intel.com>
Thu, 12 May 2011 07:53:42 +0000 (08:53 +0100)
1). Add explicitly uc=pcc=1 fatal error detect, since under such case
the s/ar/over bits status is undefined and hence may be
mis-cleaned. Explicit fatal detect return 0 indicate stick MSR bank
will have chance to be handled after reboot by polling;
2). Fix a little bug for case SRAR, over bit should be 0 when need
clear bank, otherwise it would reset system;
3). When clear bank, add clear MCi_ADDR/MISC if it's valid, according
to Intel SDM;

Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
xen/arch/x86/cpu/mcheck/mce.c
xen/arch/x86/cpu/mcheck/mce_intel.c

index 8bd308d75ca39852d04fabcca48383cd580aa5d4..3e61ee389adfe60b899271264d213622f25b6ced 100644 (file)
@@ -135,6 +135,21 @@ void mcabanks_free(struct mca_banks *banks)
         xfree(banks->bank_map);
     xfree(banks);
 }
+
+static void mcabank_clear(int banknum)
+{
+    uint64_t status;
+
+    status = mca_rdmsr(MSR_IA32_MCx_STATUS(banknum));
+
+    if (status & MCi_STATUS_ADDRV)
+        mca_wrmsr(MSR_IA32_MCx_ADDR(banknum), 0x0ULL);
+    if (status & MCi_STATUS_MISCV)
+        mca_wrmsr(MSR_IA32_MCx_MISC(banknum), 0x0ULL);
+
+    mca_wrmsr(MSR_IA32_MCx_STATUS(banknum), 0x0ULL);
+}
+
 /* Judging whether to Clear Machine Check error bank callback handler
  * According to Intel latest MCA OS Recovery Writer's Guide, 
  * whether the error MCA bank needs to be cleared is decided by the mca_source
@@ -345,8 +360,8 @@ mctelem_cookie_t mcheck_mca_logout(enum mca_source who, struct mca_banks *bankma
 
         /* By default, need_clear = 1 */
         if (who != MCA_MCE_SCAN && need_clear)
-            /* Clear status */
-            mca_wrmsr(MSR_IA32_MCx_STATUS(i), 0x0ULL);
+            /* Clear bank */
+            mcabank_clear(i);
         else if ( who == MCA_MCE_SCAN && need_clear)
             mcabanks_set(i, clear_bank);
 
@@ -601,15 +616,11 @@ void mcheck_cmn_handler(struct cpu_user_regs *regs, long error_code,
 void mcheck_mca_clearbanks(struct mca_banks *bankmask)
 {
     int i;
-    uint64_t status;
 
-    for (i = 0; i < 32 && i < nr_mce_banks; i++) {
+    for (i = 0; i < nr_mce_banks; i++) {
         if (!mcabanks_test(i, bankmask))
             continue;
-        status = mca_rdmsr(MSR_IA32_MCx_STATUS(i));
-        if (!(status & MCi_STATUS_VAL))
-            continue;
-        mca_wrmsr(MSR_IA32_MCx_STATUS(i), 0x0ULL);
+        mcabank_clear(i);
     }
 }
 
index dbbf9751ef2038885471ae5f9fe67fb6334a75cf..44237a4274978ee7f570524f83f5f1ad649bcb8a 100644 (file)
@@ -903,17 +903,25 @@ static int intel_need_clearbank_scan(enum mca_source who, u64 status)
         else return 0;
     }
     else if ( who == MCA_MCE_SCAN) {
+        if ( !ser_support )
+            return 0;
+        /* 
+         * For fatal error, it shouldn't be cleared so that sticky bank
+         * have chance to be handled after reboot by polling
+         */
+        if ( (status & MCi_STATUS_UC) && (status & MCi_STATUS_PCC) )
+            return 0;
         /* Spurious need clear bank */
-        if ( ser_support && !(status & MCi_STATUS_OVER)
+        else if ( !(status & MCi_STATUS_OVER)
                     && (status & MCi_STATUS_UC) && !(status & MCi_STATUS_EN))
             return 1;
         /* SRAR OVER=0 clear bank. OVER = 1 have caused reset */
-        else if ( ser_support && (status & MCi_STATUS_UC)
+        else if ( (status & MCi_STATUS_UC)
                     && (status & MCi_STATUS_S) && (status & MCi_STATUS_AR )
-                    && (status & MCi_STATUS_OVER) )
+                    && !(status & MCi_STATUS_OVER) )
             return 1;
         /* SRAO need clear bank */
-        else if ( ser_support && !(status & MCi_STATUS_AR) 
+        else if ( !(status & MCi_STATUS_AR) 
                     && (status & MCi_STATUS_S) && (status & MCi_STATUS_UC))
             return 1; 
         else